我正在尝试使用 Scrapy 提交动态生成的用户登录表单,然后解析页面上与成功登录相对应的 HTML。
我想知道如何使用 Scrapy 或 Scrapy 和 Selenium 的组合来做到这一点。Selenium 使得在 DOM 上找到元素成为可能,但我想知道是否有可能在获得完整的 HTML 后将控制权“交还”给 Scrapy,以允许它执行表单提交并保存必要的 cookie ,会话数据等以抓取页面。
基本上,我认为 Selenium 是必要的唯一原因是因为我需要在 Scrapy 查找<form>元素之前从 Javascript 呈现页面。但是,有没有其他替代方法?
谢谢!
编辑:这个问题类似于这一个,但不幸的请求库而不是硒或Scrapy接受的答案交易。尽管在某些情况下可能出现这种情况(观看此内容以了解更多信息),但正如 alecxe 指出的那样,如果“页面的某些部分 [例如表单] 通过 API 调用加载并在帮助下插入到页面中,则可能需要 Selenium在浏览器中执行的 javascript 代码”。
我想废弃一个包含带有过滤选项的组合框的网页。基本 url 相同,但请求有效负载取决于选定的组合框值。我有一个可用选项列表,我创建了一个循环,它遍历组合框值并执行请求。代码如下:
def parse_product_lines(self, response):
options = json.loads(response.body_as_unicode())
product_lines = options['products']
for product_line in product_lines:
payload = self.prepare_payload(product_line)
scrapy.Request('http://example.com',
method="POST",
body=urllib.urlencode(payload),
callback=self.parse_items)
def parse_items(self, response):
print response
Run Code Online (Sandbox Code Playgroud)
,但不执行请求。有人知道那里发生了什么吗?
我创建了一个非常慢的新 Scrapy 蜘蛛。它每秒只能抓取大约两页,而我创建的其他 Scrapy 爬虫的抓取速度要快得多。
我想知道是什么导致了这个问题,以及如何解决这个问题。该代码与其他蜘蛛并没有太大不同,我不确定它是否与问题有关,但如果您认为可能涉及到它,我会添加它。
事实上,我的印象是请求不是异步的。我从来没有遇到过这种问题,而且我对 Scrapy 还是很陌生。
编辑
这是蜘蛛:
class DatamineSpider(scrapy.Spider):
name = "Datamine"
allowed_domains = ["domain.com"]
start_urls = (
'http://www.example.com/en/search/results/smth/smth/r101/m2108m',
)
def parse(self, response):
for href in response.css('.searchListing_details .search_listing_title .searchListing_title a::attr("href")'):
url = response.urljoin(href.extract())
yield scrapy.Request(url, callback=self.parse_stuff)
next_page = response.css('.pagination .next a::attr("href")')
next_url = response.urljoin(next_page.extract()[0])
yield scrapy.Request(next_url, callback=self.parse)
def parse_stuff(self, response):
item = Item()
item['value'] = float(response.xpath('//*[text()="Price" and not(@class)]/../../div[2]/span/text()').extract()[0].split(' ')[1].replace(',',''))
item['size'] = float(response.xpath('//*[text()="Area" and not(@class)]/../../div[2]/text()').extract()[0].split(' ')[0].replace(',', '.'))
try:
item['yep'] = float(response.xpath('//*[text()="yep" and not(@class)]/../../div[2]/text()').extract()[0])
except IndexError:
print …Run Code Online (Sandbox Code Playgroud) 我试图从子站点中抓取详细信息并与通过 site 抓取的详细信息合并。我一直在研究 stackoverflow 以及文档。但是,我仍然无法让我的代码工作。似乎我从子站点提取其他详细信息的功能不起作用。如果有人能看一下,我将不胜感激。
# -*- coding: utf-8 -*-
from scrapy.spiders import Spider
from scrapy.selector import Selector
from scrapeInfo.items import infoItem
import pyodbc
class scrapeInfo(Spider):
name = "info"
allowed_domains = ["http://www.nevermind.com"]
start_urls = []
def start_requests(self):
#Get infoID and Type from database
self.conn = pyodbc.connect('DRIVER={SQL Server};SERVER=server;DATABASE=dbname;UID=user;PWD=password')
self.cursor = self.conn.cursor()
self.cursor.execute("SELECT InfoID, category FROM dbo.StageItem")
rows = self.cursor.fetchall()
for row in rows:
url = 'http://www.nevermind.com/info/'
InfoID = row[0]
category = row[1]
yield self.make_requests_from_url(url+InfoID, InfoID, category, self.parse)
def make_requests_from_url(self, …Run Code Online (Sandbox Code Playgroud) 我正在使用scrapy来解析具有以下形式的网站:
<form id="form1"...>
<select name="codes" multiple="multiple"...>
<option value="0">Option one</option>
<option value="1">Option two</option>
<option value="2">Option three</option>
....
</select>
</form>
Run Code Online (Sandbox Code Playgroud)
我正在填写并使用以下代码提交表单:
submit_form = FormRequest.from_response(response,
formxpath="//form[@id='form1']",
formdata={'codes': '0'},
callback=self.parse_table)
yield submit_form
Run Code Online (Sandbox Code Playgroud)
如何在表单数据中提交多个代码?我试过了:
formdata={'codes': '["0", "1", "2"]'},
formdata={'codes': ['0', '1', '2']},
Run Code Online (Sandbox Code Playgroud)
没有任何运气。
编辑:
表单有额外的输入控件,其中一些是隐藏的,它们在表单中正确传递。我在表单提交后看到的就像服务器返回到与表单相同的页面,当我期待一个新页面的表格实际上包含我想要检索的数据时。
我对服务器后端知之甚少,只知道它是用 .NET 2.0 构建的。这是一个非常古老的网站,来自政府的依赖。
谢谢。
我想将scrapy作为python脚本运行,但我不知道如何正确设置设置或如何提供它们。我不确定这是否是设置问题,但我认为是。
我的配置:
我接受了https://doc.scrapy.org/en/latest/topics/practices.html#run-scrapy-from-a-script的建议来让它运行。我对以下建议有一些问题:
如果您在 Scrapy 项目中,则可以使用一些额外的帮助程序将这些组件导入项目中。您可以自动导入将其名称传递给 CrawlerProcess 的蜘蛛,并使用 get_project_settings 获取带有项目设置的 Settings 实例。
那么“在 Scrapy 项目中”是什么意思?当然,我必须导入库并安装依赖项,但我想避免使用scrapy crawl xyz.
这是 myScrapy.py 的代码
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.item import Item, Field
import os, argparse
#Initialization of directories
projectDir = os.path.dirname(os.path.realpath('__file__'))
generalOutputDir = os.path.join(projectDir, 'output')
parser = argparse.ArgumentParser()
parser.add_argument("url", help="The url which you want to scan", type=str)
args …Run Code Online (Sandbox Code Playgroud) 在问了我的最后一个问题(如何将参数传递给scrapy管道对象)之后,我试图更好地理解scrapy中管道和爬虫之间的关系
答案之一是:
@classmethod
def from_crawler(cls, crawler):
# Here, you get whatever value was passed through the "table" parameter
settings = crawler.settings
table = settings.get('table')
# Instantiate the pipeline with your table
return cls(table)
def __init__(self, table):
_engine = create_engine("sqlite:///data.db")
_connection = _engine.connect()
_metadata = MetaData()
_stack_items = Table(table, _metadata,
Column("id", Integer, primary_key=True),
Column("detail_url", Text),
_metadata.create_all(_engine)
self.connection = _connection
self.stack_items = _stack_items
Run Code Online (Sandbox Code Playgroud)
我很困惑:
@classmethod
def from_crawler(cls, crawler):
# Here, you get whatever value was passed through the "table" parameter …Run Code Online (Sandbox Code Playgroud) 我怎样才能在scrapy shell中输出结果到一个文件,最好是csv?
我的bpython外壳中有一个有趣的元素列表,我可以制作item它们。但是如何将其重定向到文件?
我正在从 python 的requests库转移到scrapy,并且在发出简单的 POST 请求时遇到问题。我正在设置标题和有效负载:
headers = {
'Accept':'*/*',
'Accept-Encoding':'gzip, deflate, br',
'accept-language':'en_US',
'Connection':'keep-alive',
'Content-Length':'151',
'content-type':'application/json',
'Cookie':cookie,
'Host':host,
'Origin':origin,
'Referer':referer,
'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
'x-csrf-token':token
}
payload = {"targetLocation":{"latitude":lat,"longitude":lng}}
Run Code Online (Sandbox Code Playgroud)
然后像这样提出请求:
def start_requests(self):
u = self.url
yield scrapy.Request(u, method='POST',
callback=self.parse_httpbin,
errback=self.errback_httpbin,
body=json.dumps(self.payload),
headers=self.headers)
Run Code Online (Sandbox Code Playgroud)
这一直给我 400 状态。如果我使用与requests库完全相同的标头和有效负载发出请求,它会按预期为我提供 200 状态并返回一个 json。
r = requests.post(url, headers=headers, data=json.dumps(payload), verify=False)
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
我正在编写一个 Scrapy 抓取器,它使用 CrawlSpider 来抓取站点,查看其内部链接,并抓取任何外部链接(域与原始域不同的域的链接)的内容。
我设法用 2 条规则做到了这一点,但它们基于被抓取的站点的域。如果我想在多个网站上运行它,我会遇到一个问题,因为我不知道我目前在哪个“start_url”上,所以我无法适当地更改规则。
到目前为止,这是我想到的,它适用于一个网站,但我不确定如何将其应用于网站列表:
class HomepagesSpider(CrawlSpider):
name = 'homepages'
homepage = 'http://www.somesite.com'
start_urls = [homepage]
# strip http and www
domain = homepage.replace('http://', '').replace('https://', '').replace('www.', '')
domain = domain[:-1] if domain[-1] == '/' else domain
rules = (
Rule(LinkExtractor(allow_domains=(domain), deny_domains=()), callback='parse_internal', follow=True),
Rule(LinkExtractor(allow_domains=(), deny_domains=(domain)), callback='parse_external', follow=False),
)
def parse_internal(self, response):
# log internal page...
def parse_external(self, response):
# parse external page...
Run Code Online (Sandbox Code Playgroud)
这可能可以通过在调用刮刀时将 start_url 作为参数传递来完成,但我正在寻找一种在刮刀本身内以编程方式执行此操作的方法。
有任何想法吗?谢谢!
西蒙。
python ×10
scrapy ×10
web-crawler ×3
web-scraping ×2
csv ×1
forms ×1
function ×1
merge ×1
output ×1
python-2.7 ×1
request ×1
selenium ×1