我正在使用scrapy来抓取一个网站,该网站似乎在每个网址末尾的查询字符串中附加了随机值。这使得爬行成为一种无限循环。
如何让scrapy忽略URL的查询字符串部分?
答案 0 :(得分:22)
示例代码:
from urlparse import urlparse
o = urlparse('http://url.something.com/bla.html?querystring=stuff')
url_without_query_string = o.scheme + "://" + o.netloc + o.path
示例输出:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from urlparse import urlparse
>>> o = urlparse('http://url.something.com/bla.html?querystring=stuff')
>>> url_without_query_string = o.scheme + "://" + o.netloc + o.path
>>> print url_without_query_string
http://url.something.com/bla.html
>>>
答案 1 :(得分:10)
url_query_cleaner
模块中有一个函数w3lib.url
(由scrapy本身使用)来清理URL,只保留允许的参数列表。
答案 2 :(得分:6)
提供一些代码,以便我们为您提供帮助。
如果您将CrawlSpider
和Rule
与SgmlLinkExtractor
一起使用,请为proccess_value
构造函数的SgmlLinkExtractor
参数提供自定义函数。
def delete_random_garbage_from_url(url):
cleaned_url = ... # process url somehow
return cleaned_url
Rule(
SgmlLinkExtractor(
# ... your allow, deny parameters, etc
process_value=delete_random_garbage_from_url,
)
)
答案 3 :(得分:3)
您可以使用urllib.parse.urlsplit()
function。结果是structured parse result,一个具有附加功能的命名元组。
使用namedtuple._replace()
方法更改已解析的结果值,然后使用SplitResult.geturl()
method重新获取URL字符串。
要删除查询字符串,请将query
的值设置为None
:
from urllib.parse import urlsplit
updated_url = urlsplit(url)._replace(query=None).geturl()
演示:
>>> from urllib.parse import urlsplit
>>> url = 'https://example.com/example/path?query_string=everything+after+the+questionmark'
>>> urlparse.urlsplit(url)._replace(query=None).geturl()
'https://example.com/example/path'
对于Python 2,urlparse.urlsplit()
name下提供了相同的功能。
您也可以使用urllparse.parse.urlparse()
function;对于没有任何path parameters的URL,结果将是相同的。这两个函数在处理路径参数的方式上有所不同。 urlparse()
仅支持路径最后一段的路径参数,而urlsplit()
将路径参数保留在路径中,从而将此类参数解析为其他代码。由于最近很少使用路径参数(后来的URL RFC完全删除了此功能),所以区别是学术上的。 urlparse()
使用urlsplit()
并且没有参数,除了额外的开销外,没有添加任何其他内容。最好直接使用urlsplit()
。
答案 4 :(得分:1)
使用此方法从url中删除查询字符串
urllink="http://url.something.com/bla.html?querystring=stuff"
url_final=urllink.split('?')[0]
print(url_final)
答案 5 :(得分:0)
如果您使用BaseSpider,在产生新请求之前,请使用urlparse从网址的查询部分手动删除随机值:
def parse(self, response):
hxs = HtmlXPathSelector(response)
item_urls = hxs.select(".//a[@class='...']/@href").extract()
for item_url in item_urls:
# remove the bad part of the query part of the URL here
item_url = urlparse.urljoin(response.url, item_url)
self.log('Found item URL: %s' % item_url)
yield Request(item_url, callback = self.parse_item)